﻿<#
.SYNOPSIS  
    Upgrades a SharePoint 2007 Shared Service Provider database to a SharePoint 2010 User Profile Service Application. 
.DESCRIPTION  
    Upgrades a SSP, updates the My Site photos and moves user profile multi-value properties to the Managed Metadata Service Application.
.NOTES
    This script must be run as the farm account or the profile databases will have the incorrect owner. 
    The managed metadata service must be configured before running this script.
.LINK  
    http://7up.codeplex.com 
#>

Write-Host ("   Adding Profile Service Applications ({0})..." -f [DateTime]::Now.ToString())

#add SharePoint snap in
if ((Get-PSSnapin -Name  Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue) -eq $null) 
{ 
    Add-PsSnapin  Microsoft.SharePoint.PowerShell 
}

#get config
$config = [xml](Get-Content Upgrade.xml)

#ensure running as farm account
# if you don't do this, the profile databases will have the wrong owners
# You will have issues with the synchronization service
# and errors such as "No User Profile Service Application"
$curUser = $env:USERDOMAIN+"\"+$env:USERNAME
Write-Host ("      Current user is {0}" -f $curUser)
If ($curUser -ne $config.Settings.FarmAccount)
{
	throw ("This script must be executed as the farm account '" + $config.Settings.FarmAccount + "'")
}

foreach($psa in $config.Settings.ServiceApplications.ProfileServiceApplications.ProfileServiceApplication)
{
	if($psa -ne $null)
	{
		#add service application
		$sa = Get-SPServiceApplication | Where-Object {$_.DisplayName -eq $psa.Name}
		if($sa -eq $null)
		{
			Write-Host ("      Adding '{0}' ({1})..." -f $psa.Name,[DateTime]::Now.ToString())
			$sa = New-SPProfileServiceApplication -Name $psa.Name -ApplicationPool $psa.ApplicationPool -ProfileDBName $psa.ProfileDBName -SocialDBName $psa.SocialDBName -ProfileSyncDBName $psa.ProfileSyncDBName -MySiteHostLocation $psa.MySiteHostLocation
		}
		else
		{	
			Write-Host ("      Skipping '{0}' because it already exists ({1})." -f $psa.Name, [DateTime]::Now.ToString())
		}
		
		#add proxy
		$proxyName = ($psa.Name + " Proxy")
		$sap = Get-SPServiceApplicationProxy | Where-Object {$_.DisplayName -eq $proxyName}
		if($sap -eq $null)
		{
			Write-Host ("      Adding '{0}' ({1})..." -f $proxyName, [DateTime]::Now.ToString())
			$sap = New-SPProfileServiceApplicationProxy -Name $proxyName -ServiceApplication $sa
		}
		else
		{	
			Write-Host ("      Skipping '{0}' because it already exists ({1})." -f $proxyName, [DateTime]::Now.ToString())
		}
		
		#add profile service to same proxy group as my site host
		$webApp = Get-SPWebApplication $psa.MySiteHostLocation
		$mbr = Add-SPServiceApplicationProxyGroupMember -Identity $webApp.ServiceApplicationProxyGroup -Member $sap
	
		#grant permissions
		Write-Host ("      Granting permissions on '{0}' ({1})." -f $sa.Name, [DateTime]::Now.ToString())

		#get service app admins 
		$admins = Get-SPServiceApplicationSecurity $sa -Admin

		foreach($perm in $psa.Permissions.Permission)
		{
			if($perm -ne $null)
			{
				Write-Host ("         Granting '{0}' to '{1}' ({2})." -f $perm.Rights, $perm.UserName, [DateTime]::Now.ToString())
				$principal = New-SPClaimsPrincipal -Identity $perm.UserName -IdentityType WindowsSamAccountName
				Grant-SPObjectSecurity $admins -Principal $principal -Rights $perm.Rights
			}
		}
		Set-SPServiceApplicationSecurity $sa -objectSecurity $admins -Admin

		#reset IIS
		iisreset

		#update the photo store on my site host
		Write-Host ("      Updating profile photo store for '{0}' ({1})..." -f $psa.MySiteHostLocation, [DateTime]::Now.ToString())
		Update-SPProfilePhotoStore -MySiteHostLocation $psa.MySiteHostLocation
		
		#move multi-valued properties into the managed metadata service
		foreach($prop in $psa.ManagedMetadataProperties.ManagedMetadataProperty)
		{
			if($prop -ne $null)
			{
				Write-Host ("      Moving multi-value profile property '{0}' to '{1}' ({2})..." -f $prop.Identity, $prop.TermSetName, [DateTime]::Now.ToString())
				Move-SPProfileManagedMetadataProperty -Identity $prop.Identity -TermSetName $prop.TermSetName -AvailableForTagging -ProfileServiceApplicationProxy $sap}
			}
		}
}

